<template>
  <teleport to="body">
    <transition name="list-fade">
      <div
        class="playlist"
        v-show="visible && playlist.length"
        @click="hide"
      >
        <div class="list-wrapper" @click.stop>
          <div class="list-header">
            <h1 class="title">
              <i
                class="icon"
                :class="modeIcon"
                @click.stop="changeMode"
              ></i>
              <span class="text">{{modeText}}</span>
              <span class="clear" @click="showConfirm">
                <i class="icon-clear"></i>
              </span>
            </h1>
          </div>
          <scroll
            class="list-content"
            ref="scrollRef"
          >
          <!-- 为了有过渡效果,使用transition-group来替换ul -->
            <transition-group
              ref="listRef"
              name="list"
              tag="ul"
            >
              <li
                class="item"
                v-for="song in sequenceList"
                :key="song.id"
                @click="selectItem(song)"
              >
                <i class="current" :class="getCurrentIcon(song)"></i>
                <span class="text">{{song.name}}</span>
                <span class="favorite" @click.stop="toggleFavorite(song)">
                  <i :class="getFavoriteIcon(song)"></i>
                </span>
                <span
                  class="delete"
                  @click.stop="removeSong(song)"
                  :class="{'disable': removing}"
                >
                  <i class="icon-delete"></i>
                </span>
              </li>
            </transition-group>
          </scroll>
          <div class="list-add">
            <div class="add" @click="showAddSong">
              <i class="icon-add"></i>
              <span class="text">添加歌曲到队列</span>
            </div>
          </div>
          <div class="list-footer" @click.stop="hide">
            <span>关闭</span>
          </div>
        </div>
        <Confirm
          @confirm="confirmClear"
          ref="confirm"
          text="是否清空播放列表?"
          confirmBtnText="清空"
        ></Confirm>
        <add-song ref="addSongRef"></add-song>
      </div>
    </transition>
  </teleport>
</template>

<script>
import Scroll from '../../components/base/scroll/scroll.vue';
import { ref, computed, nextTick, watch } from 'vue';
import { useStore } from 'vuex';
import useMode from './use-mode';
import useFavorite from './use-favorite';
import Confirm from '../../components/base/confirm/confirm.vue';
import addSong from '../../components/add_song/add_song.vue';

export default {
  name: 'playlist',
  components: {
    Scroll,
    Confirm,
    addSong
  },
  setup() {
    const visible = ref(false);
    const scrollRef = ref(null);
    const listRef = ref(null);
    const removing = ref(false);
    const confirm = ref(null);
    const addSongRef = ref(null);

    const store = useStore();
    const playlist = computed(() => store.state.playList);
    const sequenceList = computed(() => store.state.sequenceList);
    const currentSong = computed(() => store.getters.currentSong);

    const { modeIcon, changeMode, modeText } = useMode();
    const { getFavoriteIcon, toggleFavorite } = useFavorite();

    function hide() {
      visible.value = false;
    }
    async function show() {
      visible.value = true;
      await nextTick();
      refreshScroll();
      scrollToCurrent();
    }

    watch(currentSong, async (newSong) => {
      // currentSong变化时有可能playlist还没有被打开
      // 测试提交
      if (!visible.value || !newSong.id) {
        return;
      }
      // 删除操作会改变DOM,需要nextTick

      await nextTick();
      scrollToCurrent();
    });

    function getCurrentIcon(song) {
      if (song.id === currentSong.value.id) {
        return 'icon-play';
      }
    }
    // 初始化时滚动组件会比playlist页面先实例化,高度计算不对,所以不会滚动
    function refreshScroll() {
      // scrollRef.value.scroll为滚动组件实例
      // refresh()方法可以使滚动组件内部重新计算高度
      scrollRef.value.scroll.refresh();
    }
    // 播放列表滚动到当前播放歌曲位置
    function scrollToCurrent() {
      const index = sequenceList.value.findIndex((song) => {
        return currentSong.value.id === song.id;
      });
      if (index === -1) {
        return;
      }
      // 当前播放歌曲DOM元素
      const target = listRef.value.children[index];
      scrollRef.value.scroll.scrollToElement(target, 300);
    }

    function selectItem(song) {
      // currentSong是根据playlist计算出来的
      const index = playlist.value.findIndex((item) => {
        return item.id === song.id;
      });
      // 切换歌曲
      store.commit('setCurrentIndex', index);
      // 播放歌曲
      store.commit('setPlayingState', true);
    }

    // 删除歌曲
    function removeSong(song) {
      if (removing.value) {
        return;
      }
      removing.value = true;
      store.dispatch('removeSong', song);
      if (!playlist.value.length) {
        hide();
      }
      setTimeout(() => {
        removing.value = false;
      }, 300);
    }

    function showConfirm() {
      confirm.value.show();
    }

    function confirmClear() {
      store.dispatch('clearSongList');
      hide();
    }

    function showAddSong() {
      addSongRef.value.show();
    }

    return {
      showAddSong,
      confirmClear,
      confirm,
      showConfirm,
      removing,
      removeSong,
      visible,
      playlist,
      sequenceList,
      modeIcon,
      changeMode,
      modeText,
      getFavoriteIcon,
      toggleFavorite,
      hide,
      show,
      getCurrentIcon,
      scrollRef,
      listRef,
      scrollToCurrent,
      selectItem,
      addSongRef
    };
  }
};
</script>

<style lang="scss" scoped>
  .playlist {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 200;
    background-color: $color-background-d;
    &.list-fade-enter-active, &.list-fade-leave-active {
      transition: opacity .3s;
      .list-wrapper {
        transition: all .3s;
      }
    }
    &.list-fade-enter-from, &.list-fade-leave-to {
      opacity: 0;
      .list-wrapper {
        transform: translate3d(0, 100%, 0);
      }
    }
    .list-wrapper {
      position: fixed;
      left: 0;
      bottom: 0;
      z-index: 210;
      width: 100%;
      background-color: $color-highlight-background;
      .list-header {
        position: relative;
        padding: 20px 30px 10px 20px;
        .title {
          display: flex;
          align-items: center;
          .icon {
            margin-right: 10px;
            font-size: 24px;
            color: $color-theme-d;
          }
          .text {
            flex: 1;
            font-size: $font-size-medium;
            color: $color-text-l;
          }
          .clear {
            @include extend-click();
            .icon-clear {
              font-size: $font-size-medium;
              color: $color-text-d;
            }
          }
        }
      }
      .list-content {
        max-height: 240px;
        overflow: hidden;
        .item {
          display: flex;
          align-items: center;
          height: 40px;
          padding: 0 30px 0 20px;
          overflow: hidden;
          .current {
            flex: 0 0 20px;
            width: 20px;
            font-size: $font-size-small;
            color: $color-theme-d;
          }
          .text {
            flex: 1;
            @include no-wrap();
            font-size: $font-size-medium;
            color: $color-text-d;
          }
          .favorite {
            @include extend-click();
            margin-right: 15px;
            font-size: $font-size-small;
            color: $color-theme;
            .icon-favorite {
              color: $color-sub-theme;
            }
          }
          .delete {
            @include extend-click();
            font-size: $font-size-small;
            color: $color-theme;
            &.disable {
              color: $color-theme-d;
            }
          }
        }
      }
      .list-add {
        width: 140px;
        margin: 20px auto 30px auto;
        .add {
          display: flex;
          align-items: center;
          padding: 8px 16px;
          border: 1px solid $color-text-l;
          border-radius: 100px;
          color: $color-text-l;
          .icon-add {
            margin-right: 5px;
            font-size: $font-size-small-s;
          }
          .text {
            font-size: $font-size-small;
          }
        }
      }
      .list-footer {
        text-align: center;
        line-height: 50px;
        background: $color-background;
        font-size: $font-size-medium-x;
        color: $color-text-l;
      }
    }
  }
</style>
